package com.lg.partition40;

import java.io.*;
import java.util.Arrays;

/**
 * 极差为3，我们假设买100件（最多件），那么现在都买最便宜的和都买最贵的差 3 * 100 元钱； 这个差值在 minw>300 时无论如何都买不成另一件了，也就是说，
 * 此时可以买的最大件数就是 w/maxw 。 那么买的件数 <100 时，买最便宜的和都买最贵的差值 < 3 * 100 元钱，和上一种情况一样； 此时按照p从大到小排序，从
 * 大往小选 w/maxw 件就是答案了；
 * @author `RKC`
 * @date 2022/3/25 9:55
 */
public class P3985不开心的金明 {

    private static final int N = 110, M = 300010, INF = 0x3f3f3f3f;
    private static int[] w = new int[N], v = new int[N], f = new int[M];
    private static int n, m, maxw = -INF, minw = INF;

    private static final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    private static final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));

    public static void main(String[] args) throws IOException {
        String[] ss = reader.readLine().split(" ");
        n = Integer.parseInt(ss[0]);
        m = Integer.parseInt(ss[1]);
        for (int i = 1; i <= n; i++) {
            ss = reader.readLine().split(" ");
            int a = Integer.parseInt(ss[0]), b = Integer.parseInt(ss[1]);
            maxw = Math.max(maxw, a);
            minw = Math.min(minw, a);
            v[i] = a;
            w[i] = b;
        }
        //当最小值小于等于300时01背包做，大于300时贪心
        if (minw <= 300) {
            for (int i = 1; i <= n; i++) {
                for (int j = m; j >= v[i]; j--) {
                    f[j] = Math.max(f[j], f[j - v[i]] + w[i]);
                }
            }
            writer.write(f[m] + "\n");
        } else {
            Arrays.sort(w, 1, n + 1);
            reverse(w, 1, n);
            int ans = 0;
            for (int i = 1; i <= m / maxw; i++) ans += w[i];
            writer.write(ans + "\n");
        }
        writer.flush();
    }

    private static void reverse(int[] arr, int l, int r) {
        while (l < r) {
            int t = arr[l];
            arr[l++] = arr[r];
            arr[r--] = t;
        }
    }
}
